package com.bfxy.disruptor.common;

import java.lang.reflect.Field;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;

import com.bfxy.disruptor.common.balance.Sequence;
import com.bfxy.disruptor.common.consume.EventConsumer;

import sun.misc.Unsafe;

public final class Util {
	/**
	 * Calculate the next power of 2, greater than or equal to x.
	 * <p>
	 * From Hacker's Delight, Chapter 3, Harry S. Warren Jr.
	 *
	 * @param x Value to round up
	 * @return The next power of 2 from x inclusive
	 */
	public static int ceilingNextPowerOfTwo(final int x) {
		return 1 << (32 - Integer.numberOfLeadingZeros(x - 1));
	}

	/**
	 * Get the minimum sequence from an array of
	 * {@link com.bfxy.disruptor.common.balance.lmax.disruptor.Sequence}s.
	 *
	 * @param sequences to compare.
	 * @return the minimum sequence found or Long.MAX_VALUE if the array is empty.
	 */
	public static long getMinimumSequence(final Sequence[] sequences) {
		return getMinimumSequence(sequences, Long.MAX_VALUE);
	}

	// 获取最小的索引值
	public static long getMinimumSequence(final Sequence[] sequences, long minimum) {
		for (int i = 0, n = sequences.length; i < n; i++) {
			long value = sequences[i].get();
			minimum = Math.min(minimum, value);
		}

		return minimum;
	}

	/**
	 * Get an array of {@link Sequence}s for the passed {@link EventProcessor}s
	 *
	 * @param processors for which to get the sequences
	 * @return the array of {@link Sequence}s
	 */
	public static Sequence[] getSequencesFor(final EventConsumer... processors) {
		Sequence[] sequences = new Sequence[processors.length];
		for (int i = 0; i < sequences.length; i++) {
			sequences[i] = processors[i].getSequence();
		}

		return sequences;
	}

	private static final Unsafe THE_UNSAFE;// 权限问题，不能直接使用Unsafe对象，只能通过反射获取。
	static {
		try {
			final PrivilegedExceptionAction<Unsafe> action = new PrivilegedExceptionAction<Unsafe>() {
				public Unsafe run() throws Exception {
					Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
					theUnsafe.setAccessible(true);
					return (Unsafe) theUnsafe.get(null);
				}
			};

			THE_UNSAFE = AccessController.doPrivileged(action);
		} catch (Exception e) {
			throw new RuntimeException("Unable to load unsafe", e);
		}
	}

	/**
	 * Get a handle on the Unsafe instance, used for accessing low-level concurrency
	 * and memory constructs.
	 * 
	 * @return The Unsafe
	 */
	public static Unsafe getUnsafe() {
		return THE_UNSAFE;
	}

	/**
	 * Gets the address value for the memory that backs a direct byte buffer.
	 * 
	 * @param buffer
	 * @return The system address for the buffers
	 */
	public static long getAddressFromDirectByteBuffer(ByteBuffer buffer) {
		try {
			Field addressField = Buffer.class.getDeclaredField("address");
			addressField.setAccessible(true);
			return addressField.getLong(buffer);
		} catch (Exception e) {
			throw new RuntimeException("Unable to address field from ByteBuffer", e);
		}
	}

	/**
	 * Calculate the log base 2 of the supplied integer, essentially reports the
	 * location of the highest bit.
	 *
	 * @param i Value to calculate log2 for.
	 * @return The log2 value
	 */
	public static int log2(int i) {
		int r = 0;
		while ((i >>= 1) != 0) {
			++r;
		}
		return r;
	}
}
